home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AppsToGo / DTS.StyleChat / Menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  13.6 KB  |  530 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        Menu.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19.  
  20.  
  21. /*****************************************************************************/
  22.  
  23.  
  24.  
  25. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  26. #include "App.defs.h"        /* Get various application definitions.            */
  27. #include "App.protos.h"        /* Get the prototypes for application.            */
  28.  
  29. #ifndef __DESK__
  30. #include <Desk.h>
  31. #endif
  32.  
  33. #ifndef __ERRORS__
  34. #include <Errors.h>
  35. #endif
  36.  
  37. #ifndef __FONTS__
  38. #include <Fonts.h>
  39. #endif
  40.  
  41. #ifndef __MEMORY__
  42. #include <Memory.h>
  43. #endif
  44.  
  45. #ifndef __MENUS__
  46. #include <Menus.h>
  47. #endif
  48.  
  49. #ifndef __TOOLUTILS__
  50. #include <ToolUtils.h>
  51. #endif
  52.  
  53. #ifndef __UTILITIES__
  54. #include "Utilities.h"
  55. #endif
  56.  
  57.  
  58.  
  59. /*****************************************************************************/
  60.  
  61.  
  62.  
  63. extern Boolean    gQuitApplication;
  64. extern Boolean    gHasAppleEvents;
  65. extern OSType    gAppWindowType;
  66.  
  67. extern Boolean    gLowOnMem;
  68. extern short    gDialogErr;
  69.  
  70. static short    NewFontSize(short size);
  71.  
  72.  
  73.  
  74. /*****************************************************************************/
  75. /*****************************************************************************/
  76.  
  77. #ifdef applec
  78. #pragma segment Menu
  79. #endif
  80.  
  81. /*****************************************************************************/
  82. /*****************************************************************************/
  83.  
  84.  
  85.  
  86. /* •• Called by DTS.Lib..framework. •• */
  87.  
  88. /* Adjust the menu items.  We allow the DTS.Lib framework to do most of the work
  89. ** for us.  It will walk the menubar, and for each menu in the menubar, it will
  90. ** disable all of the menu items and then call the application at either
  91. ** AdjustMenuItems() (for document and palette windows, or for the no-window case),
  92. ** or DialogAdjustMenuItems() (for modal dialogs).  The application's job is to then
  93. ** turn on menu items that should be enabled to match the current application state.
  94. ** The initial Wannabe code for AdjustMenuItems() calls DoAdjustFileMenu() for the
  95. ** file menu, and DoAdjustEditMenu() for the edit menu.  Any other menus that may
  96. ** be added to Wannabe have all menu items enabled.  This allows menus to be added
  97. ** to the running version of Wannabe and allows them to actually do something.
  98. ** If the top-most window is a dialog, then all menus are disabled except for the
  99. ** edit menu.  Various items in the edit menu are enabled, depending on if there
  100. ** is an active TextEdit control, and what is in the clipboard. */
  101.  
  102. void    DoAdjustMenus(void)
  103. {
  104.     if (DoAdjustMBARMenus(FrontWindow(), rMenuBar))
  105.         DrawMenuBar();
  106. }
  107.  
  108.  
  109.  
  110. /*****************************************************************************/
  111.  
  112.  
  113.  
  114. /* This is called when an item is chosen from the menu bar (after calling
  115. ** MenuSelect or MenuKey).  It performs the right operation for each command.
  116. ** It is good to have both the result of MenuSelect and MenuKey go to one
  117. ** routine like this to keep everything organized. */
  118.  
  119. Boolean    DoMenuCommand(short menuID, short menuItem)
  120. {
  121.     short            undoDepth, numUndos, saveMode, daRefNum, mode, size;
  122.     Str255            str;
  123.     FileRecHndl        frHndl, newFrHndl;
  124.     WindowPtr        window;
  125.     TEHandle        te;
  126.     OSErr            err;
  127.     Boolean            handled;
  128.     TEHandle        teHndl;
  129.     TextStyle        styl;
  130.     MenuHandle        menu;
  131.     static Style    stylVal[] = {0, 0, 0, 1, 2, 4, 8, 16, 32, 64};
  132.  
  133.     handled = true;
  134.  
  135.     window = FrontWindow();
  136.     if (window)
  137.         frHndl = (FileRecHndl)GetWRefCon(window);
  138.             /* frHndl is valid only if it is one of our windows. */
  139.  
  140.     switch (menuID) {
  141.  
  142.         case mApple:
  143.             switch (menuItem) {
  144.                 case kStdAbout:        /* Bring up alert for About. */
  145.                     NewDocumentWindow(nil, 'ABOT', false);
  146.                     break;
  147.                 default:            /* All non-About items in this menu are DAs. */
  148.                     GetMenuItemText(GetMenuHandle(mApple), menuItem, str);
  149.                     daRefNum = OpenDeskAcc(str);
  150.                     break;
  151.             }
  152.             break;
  153.  
  154.         case mFile:
  155.             switch (menuItem) {
  156.                 case kStdNew:
  157.                     gDialogErr = NewDocumentWindow(&frHndl, gAppWindowType, true);
  158.                     if (gDialogErr)
  159.                         NewDocumentWindow(nil, 'ERR#', false);
  160.                     break;
  161.                 case kStdOpen:
  162.                     err = OpenDocumentWindow(&frHndl, nil, fsRdWrPerm);
  163.                     if ((err) && (err != userCanceledErr)) {
  164.                         gDialogErr = err;
  165.                         NewDocumentWindow(nil, 'ERR#', false);
  166.                     }
  167.                     break;
  168.                 case kStdClose:
  169.                     if (IsAppWindow(window)) {
  170.                         window = FrontWindowOfType(kwIsDocument, true);
  171.                         if (window)
  172.                             DisposeOneWindow(window, kClose);
  173.                     }
  174.                     else
  175.                         DisposeOneWindow(window, kClose);        /* Dispose of DA window. */
  176.                     break;
  177.                 case kStdSave:
  178.                 case kStdSaveAs:
  179.                     saveMode = (menuItem == kStdSave) ? kSave : kSaveAs;
  180.                     if ((*frHndl)->fileState.refNum == kInvalRefNum)
  181.                         saveMode = kSaveAs;
  182.                     err = SaveDocument(frHndl, window, saveMode);
  183.                     if ((err) && (err != userCanceledErr)) {
  184.                         gDialogErr = err;
  185.                         NewDocumentWindow(nil, 'ERR#', false);
  186.                     }
  187.                     break;
  188.                 case kDuplicate:
  189.                     gDialogErr = DuplicateDocument(frHndl, &newFrHndl);
  190.                     if (!gDialogErr) {
  191.                         gDialogErr = DoNewWindow(newFrHndl, nil, FrontWindowOfType(kwIsDocument, true), (WindowPtr)-1);
  192.                         if (gDialogErr)
  193.                             DisposeDocument(newFrHndl);
  194.                     }
  195.                     if (gDialogErr)
  196.                         NewDocumentWindow(nil, 'ERR#', false);
  197.                     break;
  198.                 case kStdPageSetup:
  199.                     DoSetCursor(&qd.arrow);
  200.                     PresentStyleDialog(frHndl);
  201.                     break;
  202.                 case kStdPrint:
  203.                     DoSetCursor(&qd.arrow);
  204.                     err = noErr;
  205.                     if (!(*frHndl)->d.doc.fhInfo.printRecValid)
  206.                         err = PresentStyleDialog(frHndl);
  207.                     if (!err) {
  208.                         err = PrintDocument(frHndl, true, true);
  209.                         PrintDocument(nil, false, false);
  210.                     }
  211.                     if ((err) && (err != userCanceledErr)) {
  212.                         gDialogErr = err;
  213.                         NewDocumentWindow(nil, 'ERR#', false);
  214.                     }
  215.                     break;
  216.                 case kStdQuit:
  217.                     gQuitApplication = DisposeAllWindows();
  218.                     break;
  219.                 default:
  220.                     handled = false;
  221.                     break;
  222.             }
  223.             break;
  224.  
  225.         case mEdit:            /* Call SystemEdit for DA editing & MultiFinder. */
  226. #if VH_VERSION
  227.             if (menuItem == kStdViewHier) {
  228.                 handled = false;
  229.                 break;
  230.             }
  231. #endif
  232.             if (IsAppWindow(window)) {
  233.                 switch (menuItem) {
  234.                     case kStdUndo:
  235.                     case kStdRedo:
  236.                     case kStdCut:
  237.                     case kStdCopy:
  238.                     case kStdPaste:
  239.                     case kStdClear:
  240.                         switch ((*frHndl)->fileState.sfType) {
  241.                                 /* This is written with the assumption that document types
  242.                                 ** that demand specific code will be added.  The below “if”
  243.                                 ** illustrates how to handle the edit menu for windows that
  244.                                 ** have an active TextEdit control.  The “else” shows a typical
  245.                                 ** undo/redo scenario for applications that are using the
  246.                                 ** hierarchical document package.  The clipboard features
  247.                                 ** are of course document-dependent, so a sample hasn't been
  248.                                 ** implemented here.  For a sample, see DTS.Draw. */
  249.                             default:
  250.                                 te = CTEFindActive(window);
  251.                                 if (te) {
  252.                                     if ((*te)->viewRect.left < -8192)
  253.                                         BeginFrame(window);
  254.                                     else
  255.                                         BeginContent(window);
  256.                                     if (menuItem == kStdUndo)
  257.                                         CTEUndo();
  258.                                     else
  259.                                         CTEClipboard(menuItem - kStdCut + 2);
  260.                                     EndContent(window);
  261.                                 }
  262.                                 else {
  263.                                     if (menuItem <= kStdRedo) {
  264.                                         if (!UnmapMItem(mEdit, kStdUndo)) {
  265.                                             GetUndoInfo(frHndl, &undoDepth, &numUndos);
  266.                                             DoUndoTask((*frHndl)->d.doc.root, 1 - undoDepth, true);
  267.                                         }
  268.                                         else DoUndoTask((*frHndl)->d.doc.root, menuItem - kStdUndo, true);
  269.                                     }
  270.                                     else {
  271.                                         /* Handle rest of edit menu here. */
  272.                                     }
  273.                                 }
  274.                                 break;
  275.                         }
  276.                         break;
  277.                 }
  278.             }
  279.             else SystemEdit(menuItem - 1);
  280.             break;
  281.  
  282.         case mFonts:
  283.             teHndl = CTEFindActive(nil);
  284.             if (teHndl) {
  285.                 if (menuItem <= kExtend) {
  286.                     if ((*teHndl)->selStart != (*teHndl)->selEnd)
  287.                         CTENewUndo(CTEViewFromTE(teHndl), true);
  288.                     mode = (styl.tsFace = stylVal[menuItem]) ? (doFace | doToggle) : (doFace);
  289.                     TESetStyle(mode, &styl, true, teHndl);
  290.                     CTEAdjustTEBottom(teHndl);
  291.                     CTEAdjustScrollValues(teHndl);
  292.                     SetDocDirty(frHndl);
  293.                 }
  294.                 if (menuItem == kFontSize) {
  295.                     if ((*teHndl)->selStart != (*teHndl)->selEnd)
  296.                         CTENewUndo(CTEViewFromTE(teHndl), true);
  297.                     size = 0;
  298.                     mode = doSize;
  299.                     TEContinuousStyle(&mode, &styl, teHndl);
  300.                     if (mode)
  301.                         if (!(size = styl.tsSize))
  302.                             size = 12;
  303.                     styl.tsSize = NewFontSize(size);
  304.                     if (styl.tsSize) {
  305.                         TESetStyle(doSize, &styl, true, teHndl);
  306.                         CTEAdjustTEBottom(teHndl);
  307.                         CTEAdjustScrollValues(teHndl);
  308.                         SetDocDirty(frHndl);
  309.                     }
  310.                 }
  311.                 if (menuItem >= kFirstFont) {
  312.                     if ((*teHndl)->selStart != (*teHndl)->selEnd)
  313.                         CTENewUndo(CTEViewFromTE(teHndl), true);
  314.                     menu = GetMenuHandle(mFonts);
  315.                     GetMenuItemText(menu, menuItem, str);
  316.                     GetFNum(str, &styl.tsFont);
  317.                     TESetStyle(doFont, &styl, true, teHndl);
  318.                     CTEAdjustTEBottom(teHndl);
  319.                     CTEAdjustScrollValues(teHndl);
  320.                     SetDocDirty(frHndl);
  321.                 }
  322.             }
  323.             break;
  324.  
  325.         default:
  326.             handled = false;
  327.             break;
  328.  
  329.     }
  330.  
  331.     return(handled);
  332. }
  333.  
  334.  
  335.  
  336. /*****************************************************************************/
  337.  
  338.  
  339.  
  340. Boolean    DoAdjustFileMenu(WindowPtr window)
  341. {
  342.     MenuHandle    menu;
  343.     FileRecHndl    frHndl;
  344.     short        enableItem;
  345.  
  346.     menu = GetMenuHandle(mFile);
  347.     EnableItem(menu, UnmapMItem(mFile, kStdQuit));            /* Gotta be able to quit. */
  348.  
  349.     if (IsDAWindow(window)) {
  350.         EnableItem(menu, UnmapMItem(mFile, kStdClose));        /* Let DAs do a close from the menu. */
  351.         return(false);
  352.     }
  353.  
  354.     if (!gLowOnMem) {
  355.         EnableItem(menu, UnmapMItem(mFile, kStdNew));
  356.         EnableItem(menu, UnmapMItem(mFile, kStdOpen));
  357.     }
  358.  
  359.     window = FrontWindowOfType(kwIsDocument, true);
  360.     if (window) {
  361.         EnableItem(menu, UnmapMItem(mFile, kStdClose));
  362.         frHndl = (FileRecHndl)GetWRefCon(window);
  363.         if ((*frHndl)->fileState.sfType == kDocFileType) {
  364.             enableItem = GetWindowDirty(window);
  365.             if ((*frHndl)->fileState.refNum == kInvalRefNum)
  366.                 enableItem = true;
  367.             if (enableItem)
  368.                 EnableItem(menu, UnmapMItem(mFile, kStdSave));
  369.             EnableItem(menu, UnmapMItem(mFile, kStdSaveAs));
  370.         }
  371.         EnableItem(menu, UnmapMItem(mFile, kDuplicate));
  372.         EnableItem(menu, UnmapMItem(mFile, kStdPageSetup));
  373.         EnableItem(menu, UnmapMItem(mFile, kStdPrint));
  374.     }
  375.  
  376.     return(false);
  377. }
  378.  
  379.  
  380.  
  381. /*****************************************************************************/
  382.  
  383.  
  384.  
  385. Boolean    DoAdjustEditMenu(WindowPtr window)
  386. {
  387.     MenuHandle        menu;
  388.     Boolean            menuEnabled;
  389.     FileRecHndl        frHndl;
  390.  
  391.     menu = GetMenuHandle(mEdit);
  392.  
  393.     if (IsDAWindow(window)) {
  394.         EnableItem(menu, UnmapMItem(mEdit, kStdUndo));
  395.         EnableItem(menu, UnmapMItem(mEdit, kStdCut));
  396.         EnableItem(menu, UnmapMItem(mEdit, kStdCopy));
  397.         EnableItem(menu, UnmapMItem(mEdit, kStdPaste));
  398.         EnableItem(menu, UnmapMItem(mEdit, kStdClear));
  399.         return(false);
  400.     }
  401.  
  402.     if (IsAppWindow(window)) {
  403.         frHndl = (FileRecHndl)GetWRefCon(window);
  404.         switch ((*frHndl)->fileState.sfType) {
  405. #if VH_VERSION
  406.             case kViewHierFileType:
  407.                 CTEEditMenu(&menuEnabled, mEdit, UnmapMItem(mEdit, kStdUndo),
  408.                                                  UnmapMItem(mEdit, kStdCut));
  409.                 break;
  410. #endif
  411.             default:
  412. #if VH_VERSION
  413.                 EnableItem(menu, UnmapMItem(mEdit, kStdViewHier));
  414. #endif
  415.                 CTEEditMenu(&menuEnabled, mEdit, UnmapMItem(mEdit, kStdUndo),
  416.                                                  UnmapMItem(mEdit, kStdCut));
  417.                 break;
  418.         }
  419.     }
  420.  
  421.     return(false);
  422. }
  423.  
  424.  
  425.  
  426. /*****************************************************************************/
  427.  
  428.  
  429.  
  430. Boolean    DoAdjustFontsMenu(WindowPtr window)
  431. {
  432.     MenuHandle        menu;
  433.     FileRecHndl        frHndl;
  434.     TEHandle        teHndl;
  435.     short            i, j, mode, fnum;
  436.     TextStyle        styl;
  437.     Str255            str;
  438.  
  439.     menu = GetMenuHandle(mFonts);
  440.  
  441.     for (i = CountMItems(menu); i; --i)
  442.         CheckItem(menu, i, false);
  443.  
  444.     if (!IsAppWindow(window))
  445.         return(false);
  446.  
  447.     frHndl = (FileRecHndl)GetWRefCon(window);
  448.     teHndl = CTEFindActive(nil);
  449.     if ((!teHndl) || (teHndl == (*frHndl)->d.doc.inBox))
  450.         return(false);
  451.  
  452.     for (i = CountMItems(menu); i; --i)
  453.         EnableItem(menu, i);
  454.  
  455.     mode = (doFont | doFace);
  456.     styl.tsFace = 0x7F;        /* Check out all styles. */
  457.     TEContinuousStyle(&mode, &styl, teHndl);
  458.     GetFontName(styl.tsFont, str);
  459.     GetFNum(str, &styl.tsFont);
  460.     if (mode & doFace) {
  461.         if (!(j = styl.tsFace))
  462.             CheckItem(menu, kPlain, true);
  463.         else
  464.             for (i = kBold; i <= kExtend; ++i, j >>= 1)
  465.                 if (j & 0x01)
  466.                     CheckItem(menu, i, true);
  467.     }
  468.     if (mode & doFont) {
  469.         for (i = CountMItems(menu); i >= kFirstFont; --i) {
  470.             GetMenuItemText(menu, i, str);
  471.             GetFNum(str, &fnum);
  472.             if (fnum == styl.tsFont) {
  473.                 CheckItem(menu, i, true);
  474.                 break;
  475.             }
  476.         }
  477.     }
  478.  
  479.     return(false);
  480. }
  481.  
  482.  
  483.  
  484. /*****************************************************************************/
  485.  
  486.  
  487.  
  488. static short    NewFontSize(short size)
  489. {
  490.     short        item, itype;
  491.     Handle        ihandle;
  492.     Rect        irect;
  493.     Str255        str;
  494.     WindowPtr    oldPort, ww;
  495.     DialogPtr    dialog;
  496.  
  497.     GetPort(&oldPort);
  498.  
  499.     ww     = FrontWindowOfType(kwIsDocument, true);
  500.     dialog = GetCenteredDialog(rNewFontSizeDlg, nil, ww, (WindowPtr)-1L);
  501.     if (dialog) {
  502.         SetPort(dialog);
  503.         if (size) {
  504.             GetDialogItem(dialog, 4, &itype, &ihandle, &irect);
  505.             pcpydec(str, size);
  506.             SetDialogItemText(ihandle, str);
  507.             SelectDialogItemText(dialog, 4, 0, 32767);
  508.         }
  509.         for (size = 0;;) {
  510.             ModalDialog(gKeyEquivFilterUPP, &item);
  511.             if (item == 3) break;
  512.             if (item == 1) {
  513.                 GetDialogItem(dialog, 4, &itype, &ihandle, &irect);
  514.                 GetDialogItemText(ihandle, str);
  515.                 size = p2dec(str, nil);
  516.                 if (size < 6)   size = 6;
  517.                 if (size > 128) size = 128;
  518.                 break;
  519.             }
  520.         }
  521.         DisposeDialog(dialog);
  522.     }
  523.  
  524.     SetPort(oldPort);
  525.     return(size);
  526. }
  527.  
  528.  
  529.  
  530.